﻿/*
created:     2025/08/22
filename:    common.nsh
author:      liuqian
purpose:     封装安装包的公用的操作接口(非业务逻辑的行为)
*/
!ifndef _ZYT_COMMON_NSH_
!define _ZYT_COMMON_NSH_
!ifndef ZYT_VERBOSE
!define ZYT_VERBOSE 3
!endif

!include "LogicLib.nsh"


# 宏定义
!define TLKillProcess        `!insertmacro TLKillProcessFunc`
!define TLCheckProcessRun    `!insertmacro TLCheckProcessRunFunc`
#!define TLUninstall          `!insertmacro UninstallProgram`

# 停止正在运行的程序
!macro TLKillProcessFunc ProcessName
    nsProcessW::_FindProcess "${ProcessName}"
    Pop $R0
    IntCmp $R0 0 running no_running no_running
    running:
      nsProcessW::_KillProcess "${ProcessName}"
      Sleep 200
      Pop $R0
      GoTo endding
    no_running:
      GoTo endding
    endding:
      nsProcessW::_Unload
!macroend

# 检测进程是否运行并提示
!macro TLCheckProcessRunFunc ProcessName
    nsProcessW::_FindProcess "${ProcessName}"
    Pop $R0
    IntCmp $R0 0 running no_running no_running
    running:
        MessageBox MB_ICONQUESTION|MB_YESNO "安装程序检测到${PRODUCT_NAME}正在运行，是否强行关闭并继续安装?" IDYES dokill IDNO stopit
    no_running:
        GoTo endding
    dokill:
        nsProcessW::_KillProcess "${ProcessName}"
        Sleep 200
        Pop $R0
        GoTo endding
    stopit:
        Quit
    endding:
        Pop $R0
        nsProcessW::_Unload
!macroend

# 卸载逻辑，创建卸载和安装共用的函数(在卸载的uninstall节中,调用同名函数需要加un.函数名，语法规定)
!macro UninstallProgram un
  Function ${un}UninstallProgram
    #clean history
    Delete "$INSTDIR\uninst.exe"
    Delete "$INSTDIR\${PRODUCT_NAME}.exe"
    Delete "$DESKTOP\${PRODUCT_NAME}.lnk"
    Delete "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk"
    RMDir /r "$SMPROGRAMS\${PRODUCT_NAME}\*"
    RMDir "$SMPROGRAMS\${PRODUCT_NAME}"

    #改名后卸载清理
    Delete "$DESKTOP\${CN_PRODUCT_NAME}.lnk"
    Delete "$SMPROGRAMS\${CN_PRODUCT_NAME}\${CN_PRODUCT_NAME}.lnk"
    RMDir /r "$SMPROGRAMS\CN_PRODUCT_NAME\*"
    RMDir "$SMPROGRAMS\${CN_PRODUCT_NAME}"    

    RMDir /r "$INSTDIR\*"
    RMDir "$INSTDIR"
    DeleteRegKey HKLM64 "${PRODUCT_UNINST_KEY}"
    DeleteRegKey HKLM64 "${PRODUCT_DIR_REGKEY}"
  FunctionEnd
!macroend

!insertmacro UninstallProgram ""
!insertmacro UninstallProgram "un."


Var STR_HAYSTACK
Var STR_NEEDLE
Var STR_CONTAINS_VAR_1
Var STR_CONTAINS_VAR_2
Var STR_CONTAINS_VAR_3
Var STR_CONTAINS_VAR_4
Var STR_RETURN_VAR
 
Function StrContains
  Exch $STR_NEEDLE
  Exch 1
  Exch $STR_HAYSTACK
  ; Uncomment to debug
  ;MessageBox MB_OK 'STR_NEEDLE = $STR_NEEDLE STR_HAYSTACK = $STR_HAYSTACK '
    StrCpy $STR_RETURN_VAR ""
    StrCpy $STR_CONTAINS_VAR_1 -1
    StrLen $STR_CONTAINS_VAR_2 $STR_NEEDLE
    StrLen $STR_CONTAINS_VAR_4 $STR_HAYSTACK
    loop:
      IntOp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_1 + 1
      StrCpy $STR_CONTAINS_VAR_3 $STR_HAYSTACK $STR_CONTAINS_VAR_2 $STR_CONTAINS_VAR_1
      StrCmp $STR_CONTAINS_VAR_3 $STR_NEEDLE found
      StrCmp $STR_CONTAINS_VAR_1 $STR_CONTAINS_VAR_4 done
      Goto loop
    found:
      StrCpy $STR_RETURN_VAR $STR_NEEDLE
      Goto done
    done:
   Pop $STR_NEEDLE ;Prevent "invalid opcode" errors and keep the
   Exch $STR_RETURN_VAR  
FunctionEnd
 
!macro _StrContainsConstructor OUT NEEDLE HAYSTACK
  Push `${HAYSTACK}`
  Push `${NEEDLE}`
  Call StrContains
  Pop `${OUT}`
!macroend
 
!define StrContains '!insertmacro "_StrContainsConstructor"'

!endif